package com.sleepingrain;
import java.util.concurrent.Executors;

import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnClickListener;
import android.media.AudioManager;
import android.opengl.Visibility;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;

/**
 * 
 *
 */
public class SoundActivity extends Activity
{
	protected final SoundBuffer soundBuffer = new SoundBuffer(16000,44100,2);
	protected final SoundPlayer soundPlayer = new SoundPlayer(soundBuffer);
	
	protected final BiQuad_Stereo_Filter lowShelfFilter = new BiQuad_Stereo_Filter(0,800,44100);
	protected final BiQuad_Stereo_Filter highShelfFilter = new BiQuad_Stereo_Filter(1,4000,44100);

	protected final Thread playBackThread = new Thread(soundPlayer, "playBack");
	
	protected ImageView ivIcon;
	private ImageView ivTimer;
	private TextView tvTimer;
	private boolean isTimerEnabled = false;

	private long mFadeOutTime;
	private long mRemainingTime;
	
	private int mFadeOutVolume;
	private int startVolume;
	private Handler mHandler = new Handler();
    static final int TIME_DIALOG_ID = 0;
    
    protected Toast mToast;
    
    protected PowerManager.WakeLock mWakeLock;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		soundPlayer.addFilter(lowShelfFilter);
		soundPlayer.addFilter(highShelfFilter);
	
	    PowerManager pm = (PowerManager)getSystemService(SoundActivity.POWER_SERVICE);
	    mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
	}

	/* (non-Javadoc)
	 * @see com.sleepingrain.SoundActivity#onStart()
	 */
	@Override
	protected void onStart() {
		super.onStart();
		startPlayer();
	}
	
	/* (non-Javadoc)
	 * @see com.sleepingrain.SoundActivity#onStop()
	 */
	@Override
	protected void onStop() {
		super.onStop();
		stopPlayer();
	}
	
	/**
	 * Function to initialize the ui elements
	 */
	protected void initSoundUI()
	{
		ivIcon = (ImageView)findViewById(R.id.ivIcon);
		ivIcon.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				if (soundPlayer.isPaused()){
					startPlayer();
				}else{
					stopPlayer();
				}
				
			}
		});
			
		ivTimer = (ImageView)findViewById(R.id.ivTimer);
		if(ivTimer != null) {
			ivTimer.setOnClickListener(new View.OnClickListener() {
				
				@Override
				public void onClick(View v) {
					if(!isTimerEnabled){
						showDialog(TIME_DIALOG_ID);
					} else {
						stopTimer();
					}
				}
			});
		}	
		
		tvTimer = (TextView)findViewById(R.id.tvTimer);
	}
	
	/**
	 * Function to start the sound player and acquire the wake lock
	 */
	public void startPlayer()
	{
		soundPlayer.resume();
		mWakeLock.acquire();
	}
	
	/**
	 * Function to stop the sound player and release the wake lock
	 */
	public void stopPlayer()
	{
		soundPlayer.pause();
		if(mWakeLock.isHeld()){
			mWakeLock.release();
		}
	}
	
	/**
	 * Function to show a toast on the display
	 * @param text the text to show
	 */
	protected void showToast(CharSequence text)
	{
		if(mToast == null){
			mToast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT);
			mToast.setGravity(Gravity.BOTTOM,0,10);
		}
		else{
			mToast.setText(text);
		}
		mToast.show();
	}
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		return super.onKeyDown(keyCode, event);
	}
	
	protected void setVolume(int volume) {
		soundPlayer.setVolume(volume/100.0f);
	}
	
	protected int getVolume(){
		return (int) (soundPlayer.getVolume()*100.0f);
	}
	
	protected void setTreble(int treble)
	{
		highShelfFilter.setGain(((float)treble-50.0f)/10.0f);
		Log.d("Treble:", String.valueOf(highShelfFilter.gain()));
	}
	
	protected int getTreble()
	{
		return (int)(highShelfFilter.gain()*10.0f+50.0f);
	}
	
	protected void setBass(int bass)
	{
		lowShelfFilter.setGain(((float)bass-50.0f)/10.0f);
		Log.d("Bass:", String.valueOf(lowShelfFilter.gain()));
	}
	protected int getBass()
	{
		return (int)(lowShelfFilter.gain()*10.0f+50.0f);
	}
	
	
	/*------------------------- Timer Section -------------------------------*/
	
	@Override
	protected Dialog onCreateDialog(int id) {
	    switch (id) {
	    case TIME_DIALOG_ID:
	        return new TimePickerDialog(this,
	                mTimeSetListener, 0, 0, true);
	    }
	    return null;
	}
	
	// the callback received when the user "sets" the time in the dialog
	private TimePickerDialog.OnTimeSetListener mTimeSetListener =
	    new TimePickerDialog.OnTimeSetListener() {
	        public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
	            startTimer((hourOfDay*60+minute)*60000);
	        }
	    };   
	    
	  /**
	   * Function to convert a time value (ms) to a readable format  
	   * @param time the time to convert
	   * @return the time in a readable format
	   */
	  public String timeToString(long time)
	  {
		  int seconds = (int)((time/1000) % 60);
		  int minutes = (int)((time/60000) % 60);
		  int hours = (int)((time/3600000) % 24);
		  
		  String secondsStr = (seconds<10 ? "0" : "")+ seconds;
		  String minutesStr = (minutes<10 ? "0" : "")+ minutes;
		  String hoursStr = (hours<10 ? "0" : "")+ hours;
		  return new String(hoursStr + ":" + minutesStr + ":" + secondsStr);
	  }
	   
	  /**
	   * Function to start the timer
	   * @param delay the delay of the timer
	   */
	   public void startTimer(long delay) {
		   isTimerEnabled = true;
		   ivTimer.setImageResource(R.drawable.ic_timer_on);
		   tvTimer.setVisibility(View.VISIBLE);
		   tvTimer.setText(timeToString(delay));
		   
		   mRemainingTime = delay;
		   mFadeOutTime = delay / 10;
		   mHandler.removeCallbacks(mUpdateTimeTask);
	       mHandler.post(mUpdateTimeTask);
	   }

	   /**
	    * Function to stop the timer
	    */
	   public void stopTimer(){
		   isTimerEnabled = false;
		   ivTimer.setImageResource(R.drawable.ic_timer_off);
		   mHandler.removeCallbacks(mUpdateTimeTask);
		   tvTimer.setVisibility(View.INVISIBLE);
	   }
	
	   /**
	    * Callback function for the timer
	    */
	   private Runnable mUpdateTimeTask = new Runnable() {
		   public void run() { 
			      
			   if(mRemainingTime <= 0) {
				   stopTimer();
				   stopPlayer();
				   
				   // reset volume
				   setVolume(startVolume);
			   }
		       else if(mRemainingTime == mFadeOutTime) {
		    		   startVolume = getVolume();	 
		    		   mFadeOutVolume = getVolume();	    		   
		       }
		       else if(mRemainingTime < mFadeOutTime) {   
		    	   mFadeOutVolume -= startVolume/(mFadeOutTime/1000);
		    	   setVolume(mFadeOutVolume);
		       }

			   if(isTimerEnabled) {
				   mRemainingTime -= 1000;
				   mHandler.postDelayed(mUpdateTimeTask, 1000);
				   tvTimer.setText(timeToString(mRemainingTime));
			   }
		   }
		};
	}

